package org.pf.base.pfBlocks
{
	import Box2D.Dynamics.b2Body;
	import com.demonsters.debugger.MonsterDebugger;
	import flash.display.Sprite;
	import flash.events.Event;
	import org.pf.base.PFBlock;
	import org.pf.constructor.staff.PFBodyGraphics;
	import org.pf.interfaces.IPFController;
	import org.pf.semaphore.events.PFStorageBodyTweensEvent;
	
	/**
	 * ...
	 * @author zeksa'
	 */
	public class PFController extends PFBlock implements IPFController
	{
		public function PFController(name:String)
		{
			super(PFBlock.CONTROLLER_BLOCK);
			_name = name;
		}
		
		override public function activate():void
		{
		
		}
		
		override public function deactivate():void
		{
		}
		
		override public function safe_deactivate():void
		{
			var func:Function = function(e:Event):void
			{
				_prince.get_SystemCache().stage.removeEventListener(Event.ENTER_FRAME, func);
				trace("Controller " + _name + " has been safely deactivated");
				MonsterDebugger.trace("Controller", _name, "has been safely deactivated");
			}
			_prince.get_SystemCache().stage.addEventListener(Event.ENTER_FRAME, func);
		}
		
		public final function connectToBody(bodyName:String):b2Body
		{
			var body:b2Body;
			for (var b:b2Body = _prince.get_SystemCache().currentWorld.GetBodyList(); b; b = b.GetNext())
			{
				if (b.GetUserData() && b.GetUserData().bodyName == bodyName)
				{
					body = b;
					break;
				}
			}
			return body;
		}
		
		public final function setTweenToBody(bodyName:String, tweenName:String):void
		{
			var body:b2Body;
			var tweenClass:Class;
			for (var b:b2Body = _prince.get_SystemCache().currentWorld.GetBodyList(); b; b = b.GetNext())
			{
				if (b.GetUserData() && b.GetUserData().bodyName == bodyName)
				{
					body = b;
					break;
				}
			}
			body.GetUserData().bodyGraphics.inTweener = false;
			
			body.GetUserData().bodyGraphics.inTweener = true;
			//TODO:set correct animation stating
			for (var i:int = 0; i < systemCache.currentCache.currentLevel.levelTweens.length; i++)
			{
				tweenClass = systemCache.currentCache.currentLevel.levelTweens[i] as Class;
				if (tweenClass.NAME == tweenName)
				{
					break;
				}
			}
			set_body_animation(body.GetUserData().bodyName,body.GetUserData().bodyGraphics, tweenClass);
			//systemCache.currentCache.bodyTweens.set_animation(body.GetUserData().bodyGraphics, bodyName, stateName);
		}
		
		private function set_body_animation(bodyName:String,bodyGraphics:PFBodyGraphics, tweenClass:Class):void
		{
			_prince.get_SystemCache().currentCache.changeAnimationStateSemaphore.lock();
			
			for (var i:int = 0; i < _prince.get_SystemCache().currentCache.enabledAnimations.length; i++)
			{
				if (_prince.get_SystemCache().currentCache.enabledAnimations[i][0] == bodyName)
				{
					_prince.get_SystemCache().currentCache.enabledAnimations.splice(i);
				}
			}
			
			_prince.get_SystemCache().currentCache.enabledAnimations.push([bodyName, new tweenClass(bodyGraphics)]);	
			_prince.get_SystemCache().currentCache.changeAnimationStateSemaphore.unlock();
		
		}
		
		public function remove_body_animation(bodyName:String):void
		{
			for (var i:int = 0; i < _prince.get_SystemCache().currentCache.enabledAnimations.length; i++)
			{
				if (_prince.get_SystemCache().currentCache.enabledAnimations[i][0] == bodyName)
				{
					_prince.get_SystemCache().currentCache.enabledAnimations.splice(i);
				}
			}
		}
		
		public final function setTweenToSprite(spriteName:String, tweenName:String):void
		{
		}
		
		public final function removeBodyTweens(bodyName:String):void
		{
			var body:b2Body;
			for (var b:b2Body = _prince.get_SystemCache().currentWorld.GetBodyList(); b; b = b.GetNext())
			{
				if (b.GetUserData() && b.GetUserData().bodyName == bodyName)
				{
					body = b;
					break;
				}
			}
			body.GetUserData().bodyAnimating = false;
			//TODO: Optimise this two functions without cicles
			remove_body_animation(bodyName);
		}
		
		public final function removeAllAnimations():void
		{
			var body:b2Body;
			for (var b:b2Body = _prince.get_SystemCache().currentWorld.GetBodyList(); b; b = b.GetNext())
			{
				if (b.GetUserData() && b.GetUserData().bodyName)
				{
					body = b;
					body.GetUserData().bodyAnimating = true;
					body.GetUserData().bodyGraphics.sprite.dispatchEvent(new PFStorageBodyTweensEvent(PFStorageBodyTweensEvent.BODY_ANIMATION_STOP));
					remove_body_animation(b.GetUserData().bodyName);
				}
			}
		}
		
		public final function changeBackground(bckgName:String):void
		{
			if (_prince.get_SystemCache().layers.backgroundLayer)
			{
				/*_prince.get_SystemCache().layers.removeChild(_prince.get_SystemCache().layers.backgroundLayer);*/
				_prince.get_SystemCache().layers.backgroundLayer = null;
			}
			_prince.get_SystemCache().layers.backgroundLayer = systemCache.currentCache.getImage("background");
		/*_prince.get_SystemCache().stage.addChild(_prince.get_SystemCache().layers.backgroundLayer);
		 _prince.get_SystemCache().stage.setChildIndex(_prince.get_SystemCache().layers.backgroundLayer, 0);*/
		}
		
		public final function registerController(ControllerClass:Class):void
		{
			var controller:PFController = new ControllerClass();
			_prince.get_SystemPool().add(controller);
			controller.activate();
		}
		
		public final function retrieveController(name:String):IPFController
		{
			return _prince.get_SystemPool().extract(PFBlock.CONTROLLER_BLOCK, name) as IPFController;
		}
		
		public final function unregisterController(controllerName:String):void
		{
			_prince.get_SystemPool().extract(PFBlock.CONTROLLER_BLOCK, controllerName).deactivate();
			_prince.get_SystemPool().extract(PFBlock.CONTROLLER_BLOCK, controllerName).safe_deactivate();
			_prince.get_SystemPool().destroy(PFBlock.CONTROLLER_BLOCK, controllerName);
		}
		
		public final function registerParticle(ParticleClass:Class):void
		{
			var particle:PFParticle = new ParticleClass();
			_prince.get_SystemPool().add(particle);
			particle.init();
		}
		
		public final function retrieveParticle(particleName:String):PFParticle
		{
			return _prince.get_SystemPool().extract(PFBlock.PARTICLE_BLOCK, particleName) as PFParticle;
		}
		
		public final function unregisterParticle(particleName:String):void
		{
			_prince.get_SystemPool().extract(PFBlock.PARTICLE_BLOCK, particleName).deactivate();
			_prince.get_SystemPool().destroy(PFBlock.PARTICLE_BLOCK, particleName);
		}
		
		public final function setLevel(levelName:String):void
		{
			_prince.get_Constructor().setEnviroment(levelName);
		}
		
		public final function registerLevelControllers():void
		{
			var ctrls:Array = _prince.get_SystemCache().currentCache.currentLevel.levelControllers;
			
			for (var i:int = 0; i < ctrls.length; i++)
			{
				registerController(ctrls[i]);
			}
			ctrls = null;
		}
		
		public final function unregisterLevelControllers():void
		{
			var ctrls:Array = _prince.get_SystemCache().currentCache.currentLevel.levelControllers;
			
			for (var i:int = 0; i < ctrls.length; i++)
			{
				unregisterController(ctrls[i].NAME);
			}
			ctrls = null;
		}
		
		public final function registerLevelParticles():void
		{
			var ctrls:Array = _prince.get_SystemCache().currentCache.currentLevel.levelParticles;
			
			for (var i:int = 0; i < ctrls.length; i++)
			{
				registerParticle(ctrls[i]);
			}
			ctrls = null;
		}
		
		public final function unregisterLevelParticles():void
		{
			var ctrls:Array = _prince.get_SystemCache().currentCache.currentLevel.levelParticles;
			
			for (var i:int = 0; i < ctrls.length; i++)
			{
				unregisterParticle(ctrls[i].NAME);
			}
			ctrls = null;
		}
	
	}

}